#include "mainwindow.h"
#include "./ui_mainwindow.h"

#include <QFile>
#include <QDataStream>
#include <QFileDialog>
#include <QFontDialog>
#include <QColorDialog>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->groupBox_Main->setEnabled(false);
}

MainWindow::~MainWindow()
{
    delete ui;
}

template<class T>
void MainWindow::writeByStream(T value)
{
    QFile fileDevice(m_filename);
    if (!fileDevice.open(QIODevice::WriteOnly)) {
        return;
    }

    QDataStream stream(&fileDevice);
    stream.setVersion(QDataStream::Qt_6_6);
    if (ui->radio_BigEndian->isChecked()) {
        stream.setByteOrder(QDataStream::BigEndian);
    }
    else {
        stream.setByteOrder(QDataStream::LittleEndian);
    }

    if (ui->radio_Single->isChecked()) {
        stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
    }
    else {
        stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
    }

    stream << value;
    fileDevice.close();
}

template<class T>
void MainWindow::readByStream(T &value)
{
    if (!QFile::exists(m_filename)) {
        return;
    }

    QFile fileDevice(m_filename);
    if (!fileDevice.open(QIODevice::ReadOnly)) {
        return;
    }

    QDataStream stream(&fileDevice);
    stream.setVersion(QDataStream::Qt_6_6);
    if (ui->radio_BigEndian->isChecked()) {
        stream.setByteOrder(QDataStream::BigEndian);
    }
    else {
        stream.setByteOrder(QDataStream::LittleEndian);
    }

    if (ui->radio_Single->isChecked()) {
        stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
    }
    else {
        stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
    }

    stream >> value;
    fileDevice.close();
}

void MainWindow::on_btnFile_clicked()
{
    m_filename = QFileDialog::getSaveFileName(this,
                                              "选择一个文件",
                                              QApplication::applicationDirPath(),
                                              "数据流文件(*.stream)");

    if (!m_filename.isEmpty()) {
        ui->editFilename->setText(m_filename);
        ui->actSaveAll->setEnabled(true);
        ui->actReadAll->setEnabled(true);
        ui->groupBox_Main->setEnabled(true);
    }
}

void MainWindow::on_btnFont_In_clicked()
{
    auto font = ui->btnFont_In->font();
    bool ok(false);
    font = QFontDialog::getFont(&ok, font, this);
    if (ok) {
        ui->btnFont_In->setFont(font);
    }
}

void MainWindow::on_btnColor_In_clicked()
{
    QPalette plet = ui->btnColor_In->palette();
    QColor color = plet.buttonText().color();
    color = QColorDialog::getColor(color);
    if (color.isValid()) {
        plet.setColor(QPalette::ButtonText, color);
        ui->btnColor_In->setPalette(plet);
    }
}


void MainWindow::on_btnInt8_Write_clicked()
{
    qint8 value = ui->spin_Int8->value();
    writeByStream(value);
}


void MainWindow::on_btnInt8_Read_clicked()
{
    qint8 value = 0;
    readByStream(value);
    ui->edit_Int8->setText(QString("%1").arg(value));
}


void MainWindow::on_btnUint8_Write_clicked()
{
    quint8 value = ui->spin_Uint8->value();
    writeByStream(value);
}


void MainWindow::on_btnUint8_Read_clicked()
{
    quint8 value(0);
    readByStream(value);
    ui->edit_Uint8->setText(QString("%1").arg(value));
}

void MainWindow::on_btnInt16_Write_clicked()
{
    qint16 value = ui->spin_Int16->value();
    writeByStream(value);
}

void MainWindow::on_btnInt16_Read_clicked()
{
    qint16 value(0);
    readByStream(value);
    ui->edit_Int16->setText(QString("%1").arg(value));
}

void MainWindow::on_btnUint16_Write_clicked()
{
    quint16 value = ui->spin_Uint16->value();
    writeByStream(value);
}

void MainWindow::on_btnUint16_Read_clicked()
{
    quint16 value(0);
    readByStream(value);
    ui->edit_Uint16->setText(QString("%1").arg(value));
}

void MainWindow::on_btnInt32_Write_clicked()
{
    qint32 value = ui->spin_Int32->value();
    writeByStream(value);
}

void MainWindow::on_btnInt32_Read_clicked()
{
    qint32 value(0);
    readByStream(value);
    ui->edit_Int32->setText(QString("%1").arg(value));
}

void MainWindow::on_btnInt64_Write_clicked()
{
    qint64 value = ui->spin_Int64->value();
    writeByStream(value);
}

void MainWindow::on_btnInt64_Read_clicked()
{
    qint64 value(0);
    readByStream(value);
    ui->edit_Int64->setText(QString("%1").arg(value));
}


void MainWindow::on_btnBool_Write_clicked()
{
    bool value = ui->chk_In->isChecked();
    writeByStream(value);
}


void MainWindow::on_btnBool_Read_clicked()
{
    bool value(false);
    readByStream(value);
    ui->chk_Out->setChecked(value);
}


void MainWindow::on_btnFloat16_Write_clicked()
{
    qfloat16 value = ui->spin_Float16->value();
    writeByStream(value);
}

void MainWindow::on_btnFloat16_Read_clicked()
{
    qfloat16 value(0);
    readByStream(value);
    ui->edit_Float16->setText(QString("%1").arg(value));
}

void MainWindow::on_btnFloat_Write_clicked()
{
    float value = ui->spin_Float->value();
    writeByStream(value);
}

void MainWindow::on_btnFloat_Read_clicked()
{
    float value(0);
    readByStream(value);
    ui->edit_Float->setText(QString::asprintf("%.4f", value));
}

void MainWindow::on_btnDouble_Write_clicked()
{
    double value = ui->spin_Double->value();
    writeByStream(value);
}

void MainWindow::on_btnDouble_Read_clicked()
{
    double value(0);
    readByStream(value);
    ui->edit_Double->setText(QString::asprintf("%.4f", value));
}


void MainWindow::on_btnCString_Write_clicked()
{
    char *value = ui->editCString_In->text().toLocal8Bit().data();
    writeByStream(value);
}

void MainWindow::on_btnCString_Read_clicked()
{
    char *value = nullptr;
    readByStream(value);
    ui->editCString_Out->setText(QString(value));
}

void MainWindow::on_btnQString_Write_clicked()
{
    QString value = ui->editQString_In->text();
    writeByStream(value);
}

void MainWindow::on_btnQString_Read_clicked()
{
    QString value;
    readByStream(value);
    ui->editQString_Out->setText(value);
}

void MainWindow::on_btnFont_Write_clicked()
{
    QFont font = ui->btnFont_In->font();
    writeByStream(font);
}

void MainWindow::on_btnFont_Read_clicked()
{
    QFont font;
    readByStream(font);
    ui->editFont_Out->setFont(font);
}


void MainWindow::on_btnColor_Write_clicked()
{
    QPalette plet= ui->btnColor_In->palette();
    QColor color = plet.buttonText().color();
    writeByStream(color);
}


void MainWindow::on_btnColor_Read_clicked()
{
    QColor color;
    readByStream(color);
    QPalette plet = ui->editColor_Out->palette();
    plet.setColor(QPalette::Text, color);
    ui->editColor_Out->setPalette(plet);
}


void MainWindow::on_actClearOutput_triggered()
{
    ui->edit_Int8->clear();
    ui->edit_Uint8->clear();
    ui->edit_Int16->clear();
    ui->edit_Uint16->clear();
    ui->edit_Int32->clear();
    ui->edit_Int64->clear();

    ui->edit_Float16->clear();
    ui->edit_Float->clear();
    ui->edit_Double->clear();

    ui->chk_Out->setChecked(false);

    ui->editCString_Out->clear();
    ui->editQString_Out->clear();

    QFont font = this->font();
    ui->editFont_Out->setFont(font);

    QPalette plet = this->palette();
    ui->editColor_Out->setPalette(plet);
}


void MainWindow::on_actSaveAll_triggered()
{
    QFile fileDevice(m_filename);
    if (!fileDevice.open(QIODevice::WriteOnly)) {
        return;
    }

    QDataStream stream(&fileDevice);
    stream.setVersion(QDataStream::Qt_6_6);
    if (ui->radio_BigEndian->isChecked()) {
        stream.setByteOrder(QDataStream::BigEndian);
    }
    else {
        stream.setByteOrder(QDataStream::LittleEndian);
    }

    if (ui->radio_Single->isChecked()) {
        stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
    }
    else {
        stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
    }

    qint8 int8_Value = ui->spin_Int8->value();
    stream << int8_Value;

    quint8 uint8_Value = ui->spin_Uint8->value();
    stream << uint8_Value;

    qint16 int16_Value = ui->spin_Int16->value();
    stream << int16_Value;

    quint16 uint16_Value = ui->spin_Uint16->value();
    stream << uint16_Value;

    qint32 int32_Value = ui->spin_Int32->value();
    stream << int32_Value;

    qint64 int64_Value = ui->spin_Int64->value();
    stream << int64_Value;

    bool bool_Value = ui->chk_In->isChecked();
    stream << bool_Value;

    qfloat16 float16_Value = ui->spin_Float16->value();
    stream << float16_Value;

    float float_Value = ui->spin_Float->value();
    stream << float_Value;

    double double_Value = ui->spin_Double->value();
    stream << double_Value;


    char *cstr = ui->editCString_In->text().toLocal8Bit().data();
    if (cstr != nullptr) {
        stream << cstr;
    }

    QString qstr = ui->editQString_In->text();
    if (!qstr.isEmpty()) {
        stream << qstr;
    }

    QFont font = ui->btnFont_In->font();
    stream << font;

    QPalette plet = ui->btnColor_In->palette();
    QColor color = plet.buttonText().color();
    stream << color;

    fileDevice.close();
}


void MainWindow::on_actReadAll_triggered()
{
    if (!QFile::exists(m_filename)) {
        return;
    }

    QFile fileDevice(m_filename);
    if (!fileDevice.open(QIODevice::ReadOnly)) {
        return;
    }

    QDataStream stream(&fileDevice);
    stream.setVersion(QDataStream::Qt_6_6);
    if (ui->radio_BigEndian->isChecked()) {
        stream.setByteOrder(QDataStream::BigEndian);
    }
    else {
        stream.setByteOrder(QDataStream::LittleEndian);
    }

    if (ui->radio_Single->isChecked()) {
        stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
    }
    else {
        stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
    }

    stream.startTransaction(); // 开始跟踪事物

    qint8 int8_Value = 0;
    stream >> int8_Value;
    ui->edit_Int8->setText(QString("%1").arg(int8_Value));

    quint8 uint8_Value = 0;
    stream >> uint8_Value;
    ui->edit_Uint8->setText(QString("%1").arg(uint8_Value));

    qint16 int16_Value = 0;
    stream >> int16_Value;
    ui->edit_Int16->setText(QString("%1").arg(int16_Value));

    quint16 uint16_Value = 0;
    stream >> uint16_Value;
    ui->edit_Uint16->setText(QString("%1").arg(uint16_Value));

    qint32 int32_Value = 0;
    stream >> int32_Value;
    ui->edit_Int32->setText(QString("%1").arg(int32_Value));

    qint64 int64_Value = 0;
    stream >> int64_Value;
    ui->edit_Int64->setText(QString("%1").arg(int64_Value));

    bool bool_Value = false;
    stream >> bool_Value;
    ui->chk_Out->setChecked(bool_Value);


    qfloat16 float16_Value = 0;
    stream >> float16_Value;
    ui->edit_Float16->setText(QString("%1").arg(float16_Value));

    float float_Value = 0;
    stream >> float_Value;
    ui->edit_Float->setText(QString::asprintf("%.4f", float_Value));

    double double_Value = 0;
    stream >> double_Value;
    ui->edit_Double->setText(QString::asprintf("%.4lf", double_Value));

    char *cstr = nullptr;
    stream >> cstr;
    if (!cstr) {
        ui->editCString_Out->setText(QString(cstr));
    }

    QString qstr;
    stream >> qstr;
    if (!qstr.isEmpty()) {
        ui->editQString_Out->setText(qstr);
    }

    QFont font;
    stream >> font;
    ui->editFont_Out->setFont(font);

    QColor color;
    stream >> color;
    QPalette plet = ui->editColor_Out->palette();
    plet.setColor(QPalette::Text, color);
    ui->editColor_Out->setPalette(plet);

    if (stream.commitTransaction()) {
        QMessageBox::information(this, "消息", "读取成功!");
    }
    else {
        QMessageBox::critical(this, "消息", "读取过程中有错误!");
    }

    fileDevice.close();
}

